#pragma once
#include "../Common/ThreadSync.h"

class ReadWriteLock : public FairMonitor
{
public:
    ReadWriteLock()
        : FairMonitor(),
        readingReaders(0),
        waitingWriters(0),
        writingWriters(0),
        preferWriter(true)
    {
    }
    ~ReadWriteLock()
    {
    }

public:
    void readLock()
    {   
        BeginSynchronized();

        while( writingWriters > 0 || (preferWriter && waitingWriters > 0) )
        {
            Wait();
        }
        readingReaders++;

        EndSynchronized();
    }

    void readUnlock()
    {   
        BeginSynchronized();

        readingReaders--;
        preferWriter = true;
        NotifyAll();

        EndSynchronized();
    }

    void writeLock()
    {   
        BeginSynchronized();

        waitingWriters++;

        while( readingReaders > 0 || writingWriters > 0 )
        {
            Wait();
        }

        waitingWriters--;

        writingWriters++;

        EndSynchronized();
    }

    void writeUnLock()
    {   
        BeginSynchronized();

        writingWriters--;
        preferWriter = false;
        NotifyAll();

        EndSynchronized();
    }

private:
    int readingReaders;
    int waitingWriters;
    int writingWriters;
    bool preferWriter;
};